package config

import (
	"fmt"
	"net/url"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"time"

	"kwdb-import/pkg/errors"
)

// ValidationRule 验证规则接口
type ValidationRule interface {
	Validate(value interface{}) error
	Name() string
}

// RequiredRule 必填验证规则
type RequiredRule struct {
	FieldName string
}

func (r *RequiredRule) Name() string {
	return "required"
}

func (r *RequiredRule) Validate(value interface{}) error {
	if value == nil {
		return errors.NewValidationError(fmt.Sprintf("%s is required", r.FieldName), r.FieldName, value)
	}
	
	switch v := value.(type) {
	case string:
		if strings.TrimSpace(v) == "" {
			return errors.NewValidationError(fmt.Sprintf("%s cannot be empty", r.FieldName), r.FieldName, v)
		}
	case int, int32, int64:
		// 数字类型默认不为空
	default:
		return errors.NewValidationError(fmt.Sprintf("%s has unsupported type for required validation", r.FieldName), r.FieldName, value)
	}
	
	return nil
}

// RangeRule 范围验证规则
type RangeRule struct {
	FieldName string
	Min       int64
	Max       int64
}

func (r *RangeRule) Name() string {
	return "range"
}

func (r *RangeRule) Validate(value interface{}) error {
	var num int64
	
	switch v := value.(type) {
	case int:
		num = int64(v)
	case int32:
		num = int64(v)
	case int64:
		num = v
	case string:
		var err error
		num, err = strconv.ParseInt(v, 10, 64)
		if err != nil {
			return errors.NewValidationError(fmt.Sprintf("%s must be a valid number", r.FieldName), r.FieldName, v)
		}
	default:
		return errors.NewValidationError(fmt.Sprintf("%s has unsupported type for range validation", r.FieldName), r.FieldName, value)
	}
	
	if num < r.Min || num > r.Max {
		return errors.NewValidationError(fmt.Sprintf("%s must be between %d and %d, got %d", r.FieldName, r.Min, r.Max, num), r.FieldName, num)
	}
	
	return nil
}

// RegexRule 正则表达式验证规则
type RegexRule struct {
	FieldName string
	Pattern   *regexp.Regexp
	Message   string
}

func (r *RegexRule) Name() string {
	return "regex"
}

func (r *RegexRule) Validate(value interface{}) error {
	str, ok := value.(string)
	if !ok {
		return errors.NewValidationError(fmt.Sprintf("%s must be a string for regex validation", r.FieldName), r.FieldName, value)
	}
	
	if !r.Pattern.MatchString(str) {
		message := r.Message
		if message == "" {
			message = fmt.Sprintf("%s format is invalid", r.FieldName)
		}
		return errors.NewValidationError(message, r.FieldName, str)
	}
	
	return nil
}

// URLRule URL验证规则
type URLRule struct {
	FieldName string
	Schemes   []string // 允许的协议，如 ["http", "https"]
}

func (r *URLRule) Name() string {
	return "url"
}

func (r *URLRule) Validate(value interface{}) error {
	str, ok := value.(string)
	if !ok {
		return errors.NewValidationError(fmt.Sprintf("%s must be a string for URL validation", r.FieldName), r.FieldName, value)
	}
	
	if strings.TrimSpace(str) == "" {
		return nil // 空值由RequiredRule处理
	}
	
	parsedURL, err := url.Parse(str)
	if err != nil {
		return errors.NewValidationError(fmt.Sprintf("%s is not a valid URL: %v", r.FieldName, err), r.FieldName, str)
	}
	
	if len(r.Schemes) > 0 {
		validScheme := false
		for _, scheme := range r.Schemes {
			if parsedURL.Scheme == scheme {
				validScheme = true
				break
			}
		}
		if !validScheme {
			return errors.NewValidationError(fmt.Sprintf("%s must use one of the following schemes: %v, got %s", r.FieldName, r.Schemes, parsedURL.Scheme), r.FieldName, parsedURL.Scheme)
		}
	}
	
	return nil
}

// FilePathRule 文件路径验证规则
type FilePathRule struct {
	FieldName    string
	MustExist    bool
	MustBeDir    bool
	MustBeFile   bool
	CreateIfMissing bool
}

func (r *FilePathRule) Name() string {
	return "filepath"
}

func (r *FilePathRule) Validate(value interface{}) error {
	str, ok := value.(string)
	if !ok {
		return errors.NewValidationError(fmt.Sprintf("%s must be a string for file path validation", r.FieldName), r.FieldName, value)
	}
	
	if strings.TrimSpace(str) == "" {
		return nil // 空值由RequiredRule处理
	}
	
	// 检查路径格式
	if !filepath.IsAbs(str) && !strings.HasPrefix(str, "./") && !strings.HasPrefix(str, "../") {
		// 相对路径，转换为绝对路径
		absPath, err := filepath.Abs(str)
		if err != nil {
			return errors.NewValidationError(fmt.Sprintf("%s is not a valid file path: %v", r.FieldName, err), r.FieldName, str)
		}
		str = absPath
	}
	
	// 检查文件/目录是否存在
	stat, err := os.Stat(str)
	if err != nil {
		if os.IsNotExist(err) {
			if r.MustExist {
				return errors.NewValidationError(fmt.Sprintf("%s does not exist: %s", r.FieldName, str), r.FieldName, str)
			}
			if r.CreateIfMissing {
				if r.MustBeDir {
					err = os.MkdirAll(str, 0755)
					if err != nil {
						return errors.NewValidationError(fmt.Sprintf("failed to create directory %s: %v", str, err), "directory", str)
					}
				} else if r.MustBeFile {
					// 创建父目录
					dir := filepath.Dir(str)
					err = os.MkdirAll(dir, 0755)
					if err != nil {
						return errors.NewValidationError(fmt.Sprintf("failed to create parent directory for %s: %v", str, err), "parent_directory", dir)
					}
				}
			}
			return nil
		}
		return errors.NewValidationError(fmt.Sprintf("failed to check %s: %v", r.FieldName, err), r.FieldName, str)
	}
	
	// 检查文件类型
	if r.MustBeDir && !stat.IsDir() {
		return errors.NewValidationError(fmt.Sprintf("%s must be a directory, got file: %s", r.FieldName, str), r.FieldName, str)
	}
	if r.MustBeFile && stat.IsDir() {
		return errors.NewValidationError(fmt.Sprintf("%s must be a file, got directory: %s", r.FieldName, str), r.FieldName, str)
	}
	
	return nil
}

// DurationRule 时间间隔验证规则
type DurationRule struct {
	FieldName string
	Min       time.Duration
	Max       time.Duration
}

func (r *DurationRule) Name() string {
	return "duration"
}

func (r *DurationRule) Validate(value interface{}) error {
	var duration time.Duration
	
	switch v := value.(type) {
	case time.Duration:
		duration = v
	case string:
		var err error
		duration, err = time.ParseDuration(v)
		if err != nil {
			return errors.NewValidationError(fmt.Sprintf("%s is not a valid duration: %v", r.FieldName, err), r.FieldName, v)
		}
	default:
		return errors.NewValidationError(fmt.Sprintf("%s has unsupported type for duration validation", r.FieldName), r.FieldName, value)
	}
	
	if r.Min > 0 && duration < r.Min {
		return errors.NewValidationError(fmt.Sprintf("%s must be at least %v, got %v", r.FieldName, r.Min, duration), r.FieldName, duration)
	}
	if r.Max > 0 && duration > r.Max {
		return errors.NewValidationError(fmt.Sprintf("%s must be at most %v, got %v", r.FieldName, r.Max, duration), r.FieldName, duration)
	}
	
	return nil
}

// EnumRule 枚举值验证规则
type EnumRule struct {
	FieldName    string
	AllowedValues []string
	CaseInsensitive bool
}

func (r *EnumRule) Name() string {
	return "enum"
}

func (r *EnumRule) Validate(value interface{}) error {
	str, ok := value.(string)
	if !ok {
		return errors.NewValidationError(fmt.Sprintf("%s must be a string for enum validation", r.FieldName), r.FieldName, value)
	}
	
	if strings.TrimSpace(str) == "" {
		return nil // 空值由RequiredRule处理
	}
	
	for _, allowed := range r.AllowedValues {
		if r.CaseInsensitive {
			if strings.EqualFold(str, allowed) {
				return nil
			}
		} else {
			if str == allowed {
				return nil
			}
		}
	}
	
	return errors.NewValidationError(fmt.Sprintf("%s must be one of %v, got %q", r.FieldName, r.AllowedValues, str), r.FieldName, str)
}

// Validator 验证器
type Validator struct {
	rules map[string][]ValidationRule
}

// NewValidator 创建新的验证器
func NewValidator() *Validator {
	return &Validator{
		rules: make(map[string][]ValidationRule),
	}
}

// AddRule 添加验证规则
func (v *Validator) AddRule(fieldName string, rule ValidationRule) {
	v.rules[fieldName] = append(v.rules[fieldName], rule)
}

// ValidateField 验证单个字段
func (v *Validator) ValidateField(fieldName string, value interface{}) error {
	rules, exists := v.rules[fieldName]
	if !exists {
		return nil // 没有规则，跳过验证
	}
	
	for _, rule := range rules {
		if err := rule.Validate(value); err != nil {
			return err
		}
	}
	
	return nil
}

// ValidateStruct 验证结构体
func (v *Validator) ValidateStruct(obj interface{}) error {
	// 这里可以使用反射来自动验证结构体字段
	// 为了简化，我们先实现手动验证
	return nil
}

// ConfigValidator 配置验证器
type ConfigValidator struct {
	validator *Validator
}

// NewConfigValidator 创建配置验证器
func NewConfigValidator() *ConfigValidator {
    validator := NewValidator()
	
	// 添加数据库配置验证规则
	validator.AddRule("host", &RequiredRule{FieldName: "host"})
	validator.AddRule("port", &RangeRule{FieldName: "port", Min: 1, Max: 65535})
	validator.AddRule("database", &RequiredRule{FieldName: "database"})
	validator.AddRule("username", &RequiredRule{FieldName: "username"})
	

	
	// 添加日志级别验证规则
	validator.AddRule("log_level", &EnumRule{
		FieldName: "log_level",
		AllowedValues: []string{"debug", "info", "warn", "error", "fatal"},
		CaseInsensitive: true,
	})

	// 添加执行模式验证规则
	validator.AddRule("execution_mode", &EnumRule{
		FieldName: "execution_mode",
		AllowedValues: []string{"batch", "streaming"},
		CaseInsensitive: true,
	})
	
	// 添加超时验证规则
	validator.AddRule("timeout", &DurationRule{
		FieldName: "timeout",
		Min: time.Second,
		Max: time.Hour,
	})
	
	// 添加批处理大小验证规则
	validator.AddRule("batch_size", &RangeRule{FieldName: "batch_size", Min: 1, Max: 10000})
	
	// 添加并发数验证规则
	validator.AddRule("max_connections", &RangeRule{FieldName: "max_connections", Min: 1, Max: 1000})
	
	return &ConfigValidator{
		validator: validator,
	}
}

// ValidateConfig 验证配置
func (cv *ConfigValidator) ValidateConfig(config *Config) error {
    if config == nil {
        return errors.NewValidationError("config cannot be nil", "config", config)
    }
    
    // 验证数据库配置
    if err := cv.validator.ValidateField("host", config.Host); err != nil {
        return err
    }
    if err := cv.validator.ValidateField("port", config.Port); err != nil {
        return err
    }
    // 兼容顶层 DBName 与嵌套 Database 的数据库名
    dbName := config.DBName
    if dbName == "" {
        if config.Database.Name != "" {
            dbName = config.Database.Name
        } else {
            dbName = config.Database.Database
        }
    }
    if err := cv.validator.ValidateField("database", dbName); err != nil {
        return err
    }
    if err := cv.validator.ValidateField("username", config.Username); err != nil {
        return err
    }
	
	// 验证文件路径
	if err := cv.validator.ValidateField("input_file", config.InputFile); err != nil {
		return err
	}
	
	// 验证日志级别
	if err := cv.validator.ValidateField("log_level", config.LogLevel); err != nil {
		return err
	}

	// 验证执行模式
	if config.ExecutionMode != "" {
		if err := cv.validator.ValidateField("execution_mode", config.ExecutionMode); err != nil {
			return err
		}
	}
	
	// 验证超时设置
	if config.Timeout != "" {
		if err := cv.validator.ValidateField("timeout", config.Timeout); err != nil {
			return err
		}
	}
	
	// 验证批处理大小
	if config.BatchSize > 0 {
		if err := cv.validator.ValidateField("batch_size", config.BatchSize); err != nil {
			return err
		}
	}
	
	// 验证最大连接数
	if config.MaxConnections > 0 {
		if err := cv.validator.ValidateField("max_connections", config.MaxConnections); err != nil {
			return err
		}
	}
	
	// 验证SSL配置
	if config.SSLMode != "" {
		allowedSSLModes := []string{"disable", "require", "verify-ca", "verify-full"}
		sslRule := &EnumRule{
			FieldName: "ssl_mode",
			AllowedValues: allowedSSLModes,
			CaseInsensitive: true,
		}
		if err := sslRule.Validate(config.SSLMode); err != nil {
			return err
		}
	}
	
	// 验证输出目录
	if config.OutputDir != "" {
		outputRule := &FilePathRule{
			FieldName: "output_dir",
			MustBeDir: true,
			CreateIfMissing: true,
		}
		if err := outputRule.Validate(config.OutputDir); err != nil {
			return err
		}
	}
	
	return nil
}

// ValidateConnectionString 验证连接字符串
func (cv *ConfigValidator) ValidateConnectionString(connStr string) error {
	if strings.TrimSpace(connStr) == "" {
		return errors.NewValidationError("connection string cannot be empty", "connection_string", connStr)
	}
	
	// 解析连接字符串
	parsedURL, err := url.Parse(connStr)
	if err != nil {
		return errors.NewValidationError(fmt.Sprintf("invalid connection string format: %v", err), "connection_string", connStr)
	}
	
	// 验证协议
	if parsedURL.Scheme != "postgres" && parsedURL.Scheme != "postgresql" {
		return errors.NewValidationError(fmt.Sprintf("unsupported database scheme: %s", parsedURL.Scheme), "scheme", parsedURL.Scheme)
	}
	
	// 验证主机和端口
	if parsedURL.Host == "" {
		return errors.NewValidationError("connection string must specify host", "host", parsedURL.Host)
	}
	
	// 验证数据库名
	if parsedURL.Path == "" || parsedURL.Path == "/" {
		return errors.NewValidationError("connection string must specify database name", "database", parsedURL.Path)
	}
	
	return nil
}

// GetValidationSuggestions 获取验证建议
func (cv *ConfigValidator) GetValidationSuggestions(config *Config) []string {
	var suggestions []string
	
	// 检查可选配置的建议
	if config.BatchSize == 0 {
		suggestions = append(suggestions, "Consider setting batch_size for better performance (recommended: 1000-5000)")
	}
	
	if config.MaxConnections == 0 {
		suggestions = append(suggestions, "Consider setting max_connections to limit database load (recommended: 5-20)")
	}
	
	if config.Timeout == "" {
		suggestions = append(suggestions, "Consider setting timeout to avoid hanging operations (recommended: 30s-5m)")
	}
	
	if config.LogLevel == "" {
		suggestions = append(suggestions, "Consider setting log_level for better debugging (recommended: info or debug)")
	}
	
	if config.SSLMode == "" {
		suggestions = append(suggestions, "Consider setting ssl_mode for secure connections (recommended: require or verify-full)")
	}
	
	if config.OutputDir == "" {
		suggestions = append(suggestions, "Consider setting output_dir for log and error files")
	}
	
	return suggestions
}